/*
 * Copyright (C) 2006 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.swing.desktop.frame;

import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuBar;

import nu.zoom.swing.desktop.preferences.Preferences;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author johan
 * 
 */
public class ExternalWorkbenchFrame extends WorkbenchFrameDelegate {

    private JFrame frame;
    private Log log = LogFactory.getLog(getClass());
    private boolean attaching = false;

    ExternalWorkbenchFrame(final DetachableWorkbenchFrame owner,
            final JComponent content, final JMenuBar frameMenu,
            final boolean resizable, final boolean maximizable,
            final Preferences preferences, final String preferencesKey) {
        super(owner, preferences, preferencesKey, content, frameMenu,
                resizable, maximizable);
        frame = new JFrame();
        if (frameMenu != null) {
            frame.setJMenuBar(frameMenu);
        }
        frame.getContentPane().add(content);
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.addWindowListener(new WindowListener());
        layoutFrame();
    }

    @Override
    FrameVisualPreferences getFrameVisualPreferencesFromFrame() {
        Dimension size = frame.getSize();
        Point position = frame.getLocation();
        FrameVisualPreferences prefs = new FrameVisualPreferences(size.width,
                size.height, position.x, position.y);
        return prefs;
    }

    private void layoutFrame() {
        FrameVisualPreferences prefs = getFrameVisualPreferencesFromPreferences();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

        int desktopwidth = screenSize.width;
        int desktopheight = screenSize.height;
        int defaultX = 10;
        int defaultY = 10;

        Integer width = (prefs != null) ? prefs.getWidth() : null;
        Integer height = (prefs != null) ? prefs.getHeight() : null;
        Integer x = (prefs != null) ? prefs.getPositionx() : null;
        Integer y = (prefs != null) ? prefs.getPositiony() : null;

        int xValue;
        int yValue;
        int widthValue;
        int heightValue;

        if ((width == null) || (height == null) || (x == null) || (y == null)) {
            frame.pack();
            widthValue = frame.getWidth();
            heightValue = frame.getHeight();
            xValue = defaultX;
            yValue = defaultY;
        } else {
            xValue = x.intValue();
            yValue = y.intValue();
            widthValue = width.intValue();
            heightValue = height.intValue();
        }

        int xAdjusted = xValue;
        int yAdjusted = yValue;
        if ((xAdjusted < 0) || (xAdjusted > desktopwidth)) {
            xAdjusted = defaultX;
        }
        if ((yAdjusted < 0) || (yAdjusted > desktopheight)) {
            yAdjusted = defaultY;
        }

        int widthAdjusted = Math.max(widthValue, 40);
        int heightAdjusted = Math.max(heightValue, 40);
        int frameMaxWidth = xAdjusted + (int) (desktopwidth * 0.9);
        int frameMaxHeight = yAdjusted + (int) (desktopheight * 0.9);

        if (widthAdjusted > frameMaxWidth) {
            widthAdjusted = frameMaxWidth;
        }
        if (heightAdjusted > frameMaxHeight) {
            heightAdjusted = frameMaxHeight;
        }
        if (log.isTraceEnabled()) {
            log.trace("Layout frame: x=" + xAdjusted + " y=" + yAdjusted
                    + " width=" + widthAdjusted + " height=" + heightAdjusted);
        }
        frame.setLocation(xAdjusted, yAdjusted);
        frame.setSize(widthAdjusted, heightAdjusted);
        frame.validate();
    }

    @Override
    void dispose() {
        savePreferences();
        frame.dispose();
    }

    @Override
    String getTitle() {
        return frame.getTitle();
    }

    @Override
    boolean isVisible() {
        return frame.isVisible();
    }

    @Override
    void moveToFront() {
        frame.toFront();
    }

    @Override
    void delegateSetIcons(List<ImageIcon> icons) {
        ArrayList<Image> images = new ArrayList<Image>();
        for (ImageIcon imageIcon : icons) {
            images.add(imageIcon.getImage());
        }
        frame.setIconImages(images);
    }

    @Override
    void setTitle(String newTitle) {
        frame.setTitle(newTitle);
    }

    @Override
    void setVisible(boolean visible) {
        frame.setVisible(visible);
    }

    class WindowListener extends WindowAdapter {

        @Override
        public void windowClosing(WindowEvent e) {
            owner.dispose();
        }

        @Override
        public void windowClosed(WindowEvent e) {
            if (!attaching) {
                owner.fireFrameClosed();
            }
        }
    }

    @Override
    void savePreferencesAndDisposeOfNativeFrameWithoutCallbacks() {
        attaching = true;
        dispose();
    }
}
